package pers.jing.android.helper.page

import androidx.compose.ui.graphics.ImageBitmap
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.slf4j.LoggerFactory
import pers.jing.android.helper.ANDROID_SDK_PATH
import pers.jing.android.helper.AndroidSdkTools
import pers.jing.android.helper.DeviceManager
import pers.jing.android.helper.db.Database
import pers.jing.android.helper.model.CODE_SUCCESS
import pers.jing.android.helper.model.PackageInfo
import pers.jing.android.helper.model.STATE_FAILURE
import pers.jing.android.helper.model.STATE_NONE
import pers.jing.android.helper.model.STATE_SUCCESS
import pers.jing.android.helper.model.TaskState
import pers.jing.android.helper.model.UIProgressDialogState
import pers.jing.android.helper.model.UIDialogState
import pers.jing.android.helper.model.UITask
import pers.jing.android.helper.work.AutoSwipeUpWork
import pers.jing.android.helper.work.DyjsbWork
import pers.jing.android.helper.work.WorkManager
import java.util.Collections
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds

/**
 * 设备页面的ViewModel
 */
class DeviceViewModel(val database: Database, val deviceManager: DeviceManager, val workManager: WorkManager): BaseViewModel() {

    val deviceNameList = mutableListOf<String>()
    private val _curDeviceIndex = MutableStateFlow(0)
    val curDeviceIndex = _curDeviceIndex

    private val _uiProgressDialogState = MutableStateFlow(UIProgressDialogState())
    val uiProgress = _uiProgressDialogState.asStateFlow()

    private val _uiDialogState = MutableStateFlow(UIDialogState(STATE_NONE))
    val uiResult = _uiDialogState.asStateFlow()

    private val allPkgList = mutableListOf<PackageInfo>()
    private val _showPkgList = MutableStateFlow(Collections.emptyList<PackageInfo>())
    val showPkgList = _showPkgList.asStateFlow()

    private val _screenImage = MutableStateFlow(ImageBitmap(0, 0))
    val screenImage = _screenImage.asStateFlow()

    /**
     * 搜索文本
     */
    private val _searchText = MutableStateFlow("")
    val searchText = _searchText.asStateFlow()

    /**
     * 任务列表
     */
    private val _taskList = MutableStateFlow(emptyList<UITask>())
    val taskList = _taskList.asStateFlow()

    private val logger = LoggerFactory.getLogger("DeviceViewModel")

    init {
        val list = deviceManager.getDevices().map {
            it.getDeviceName()
        }
        deviceNameList.addAll(list)
    }

    /**
     * 设置当前设备索引
     */
    fun setCurDeviceIndex(serialId: String) {
        var index = deviceManager.getDevices().indexOfFirst {
            it.serialId == serialId
        }
        if (index == -1) {
            index = 0
        }
        setCurDeviceIndex(index)
    }

    /**
     * 设置当前设备索引
     */
    fun setCurDeviceIndex(index: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            _curDeviceIndex.update {
                index
            }
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path == null) {
                return@launch
            }
            val deviceList = deviceManager.getDevices()
            if (index < 0 || index >= deviceList.size) {
                return@launch
            }
            _curDeviceIndex.update {
                index
            }
            val deviceInfo = deviceList[index]
            allPkgList.clear()
            //系统应用
            var pkgList = AndroidSdkTools.getDevicePkgList(
                androidSdkPath = path,
                deviceSerialId = deviceInfo.serialId,
                system = true,
                enabled = true)
            allPkgList.addAll(pkgList)
            pkgList = AndroidSdkTools.getDevicePkgList(
                androidSdkPath = path,
                deviceSerialId = deviceInfo.serialId,
                system = true,
                enabled = false)
            allPkgList.addAll(pkgList)
            //三方应用包
            pkgList = AndroidSdkTools.getDevicePkgList(
                androidSdkPath = path,
                deviceSerialId = deviceInfo.serialId,
                system = false,
                enabled = true)
            allPkgList.addAll(pkgList)
            pkgList = AndroidSdkTools.getDevicePkgList(
                androidSdkPath = path,
                deviceSerialId = deviceInfo.serialId,
                system = false,
                enabled = false)
            allPkgList.addAll(pkgList)
            //切换设备之后, 重新搜索
            search(_searchText.value)
        }
    }

    /**
     * 更新搜索文本
     */
    fun search(searchText: String) {
        viewModelScope.launch(Dispatchers.IO) {
            _searchText.update {
                searchText
            }
            _showPkgList.update {
                allPkgList.filter {
                    it.pkgName.contains(searchText)
                }
            }
        }
    }


    /**
     * 启用或者禁用应用包
     */
    fun enableOrDisablePkg(pkgInfo: PackageInfo) {
        viewModelScope.launch(Dispatchers.IO) {
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path == null) {
                return@launch
            }
            val index = _curDeviceIndex.value
            val deviceList = deviceManager.getDevices()
            val deviceInfo = deviceList[index]
            var cResult = AndroidSdkTools.updatePkg(
                androidSdkPath = path,
                deviceSerialId = deviceInfo.serialId,
                pkgName = pkgInfo.pkgName,
                enabled = !pkgInfo.enabled)
            if (CODE_SUCCESS == cResult.code) {
                //修改成功
                val i = allPkgList.indexOfFirst {
                    it.pkgName == pkgInfo.pkgName
                }
                if (i != -1) {
                    allPkgList[i] = pkgInfo.copy(enabled = !pkgInfo.enabled)
                }
                _showPkgList.update { list ->
                    list.map { item ->
                        if (item.pkgName == pkgInfo.pkgName) {
                            item.copy(enabled = !pkgInfo.enabled)
                        } else {
                            item
                        }
                    }
                }
                _uiDialogState.update {
                    it.copy(state = STATE_SUCCESS, "操作成功")
                }
            } else {
                _uiDialogState.update {
                    it.copy(state = STATE_FAILURE, cResult.error?.joinToString(",")?:"unknown")
                }
            }
        }
    }

    /**
     * 删除应用包数据
     */
    fun deletePkgData(pkgInfo: PackageInfo) {
        viewModelScope.launch(Dispatchers.IO) {
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path == null) {
                return@launch
            }
            val index = _curDeviceIndex.value
            val deviceList = deviceManager.getDevices()
            val deviceInfo = deviceList[index]
            var cResult = AndroidSdkTools.deletePkgData(
                androidSdkPath = path,
                deviceSerialId = deviceInfo.serialId,
                pkgName = pkgInfo.pkgName)
            if (CODE_SUCCESS == cResult.code) {
                //修改成功
                _uiDialogState.update {
                    it.copy(state = STATE_SUCCESS, "操作成功")
                }
            } else {
                _uiDialogState.update {
                    it.copy(state = STATE_FAILURE, cResult.error?.joinToString(",")?:"unknown")
                }
            }
        }
    }

    /**
     * 卸载应用
     */
    fun uninstallPkg(pkgInfo: PackageInfo) {
        viewModelScope.launch(Dispatchers.IO) {
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path == null) {
                return@launch
            }
            val index = _curDeviceIndex.value
            val deviceList = deviceManager.getDevices()
            val deviceInfo = deviceList[index]
            var cResult = AndroidSdkTools.uninstallPkg(
                androidSdkPath = path,
                deviceSerialId = deviceInfo.serialId,
                pkgName = pkgInfo.pkgName)
            if (CODE_SUCCESS == cResult.code) {
                //卸载成功
                val i = allPkgList.indexOfFirst {
                    it.pkgName == pkgInfo.pkgName
                }
                if (i != -1) {
                    allPkgList.removeAt(i)
                }
                _showPkgList.update { list ->
                    list.filter { item ->
                        item.pkgName != pkgInfo.pkgName
                    }
                }
                _uiDialogState.update {
                    it.copy(state = STATE_SUCCESS, "操作成功")
                }
            } else {
                _uiDialogState.update {
                    it.copy(state = STATE_FAILURE, cResult.error?.joinToString(",")?:"unknown")
                }
            }
        }
    }

    fun install(apkPath: String) {
        viewModelScope.launch(Dispatchers.IO) {
            _uiProgressDialogState.update {
                it.copy(show = true)
            }
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path != null) {
                val index = _curDeviceIndex.value
                val deviceList = deviceManager.getDevices()
                val deviceInfo = deviceList[index]
                val serialId = deviceInfo.serialId
                var cResult = AndroidSdkTools.installApk(path, deviceSerialId = serialId, apkPath = apkPath)
                if (CODE_SUCCESS == cResult.code) {
                    //安装成功
                    _uiDialogState.update {
                        it.copy(STATE_SUCCESS, "安装成功")
                    }
                } else {
                    //安装失败
                    val msg = cResult.error?.joinToString("\n")
                    _uiDialogState.update {
                        it.copy(STATE_FAILURE, msg)
                    }
                }
            }
            _uiProgressDialogState.update {
                it.copy(false)
            }
        }
    }

    /**
     * 清除UI结果
     */
    fun clearUIResult() {
        _uiDialogState.update {
            it.copy(state = STATE_NONE)
        }
    }


    /**
     * 启动任务
     */
    fun startTask(uiTask: UITask) {
        viewModelScope.launch(Dispatchers.IO) {
            if (uiTask.id.isEmpty()) {
                _uiDialogState.update {
                    it.copy(STATE_FAILURE, "未找到设备")
                }
                return@launch
            }
            _taskList.update {
                val temp = it.filter { item ->
                    item.id != uiTask.id
                }
                temp + uiTask
            }
            val androidSdkPath = database.getConfig(ANDROID_SDK_PATH)
            if (androidSdkPath.isNullOrEmpty()) {
                _uiDialogState.update {
                    it.copy(STATE_FAILURE, "未找到设备")
                }
                showConfirmDialog("请先安装ADB")
                return@launch
            }
            val work = AutoSwipeUpWork(
                duration = Duration.parse("${uiTask.duration}m"),
                interval = Duration.parse("${uiTask.interval}s"),
                id = uiTask.id, androidSdkPath
            )
            //暂定每个设备每次只能有一个任务
            workManager.execute(work, onProgress = { progress ->
                _taskList.update {
                    it.map {
                        if (it.id == uiTask.id) {
                            if (progress > 0 && progress < 100) {
                                it.copy(
                                    progress = progress,
                                    taskState = TaskState.Running
                                )
                            } else if (progress == 100) {
                                it.copy(
                                    progress = progress,
                                    taskState = TaskState.Completed
                                )
                            } else {
                                it
                            }
                        } else {
                            it
                        }
                    }
                }
            }, onError = { error ->
                _taskList.update {
                    it.map {
                        if (it.id == uiTask.id) {
                            it.copy(progress = 0, taskState = TaskState.Completed)
                        } else {
                            it
                        }
                    }
                }
            })
        }
    }

    /**
     * 停止任务
     */
    fun stopTask(uiTask: UITask) {
        viewModelScope.launch(Dispatchers.IO) {
            //暂定每个设备每次只能有一个任务
            workManager.stopTask(uiTask.id)
            _taskList.update {
                it.map {
                    if (it.id == uiTask.id) {
                        it.copy(taskState = TaskState.Init)
                    } else {
                        it
                    }
                }
            }
        }
    }

    /**
     * 获取按当前设备序列ID
     */
    fun getCurDeviceSerialId(): String {
        val index = _curDeviceIndex.value
        val devices = deviceManager.getDevices()
        if (index >= 0 && index < devices.size) {
            return devices[index].serialId
        }
        return ""
    }

    /**
     * 记录上次tap时间
     */
    private var lastTapTime: Long? = null

    /**
     * point: 桌面应用的手机截屏的坐标
     */
    fun tap(imageDisplayWidth: Int, imageDisplayHeight: Int,
            pointX: Int, pointY: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            logger.debug("tap: ${pointX}, $pointY")
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path == null) {
                return@launch
            }
            val index = _curDeviceIndex.value
            val deviceList = deviceManager.getDevices()

            if (index < 0 || index >= deviceList.size) {
                return@launch
            }
            val deviceInfo = deviceList[index]
            val imageBitmap = _screenImage.value
            if (imageBitmap.width <= 0 || imageBitmap.height <= 0) {
                return@launch
            }
            val devicePoint = desktopToPhone(imageDisplayWidth, imageDisplayHeight,
                imageBitmap.width, imageBitmap.height, pointX, pointY)
            val curTime = System.currentTimeMillis()
            if (lastTapTime != null && curTime - lastTapTime!! < 1000L) {
                //点击之后刷新要等500毫秒, 所以点击频率不能小于500毫秒,
                logger.debug("click too frequently")
                return@launch
            }
            val cResult = AndroidSdkTools.tap(path,
                deviceSerialId = deviceInfo.serialId, point = devicePoint)
            lastTapTime = System.currentTimeMillis()
            if (CODE_SUCCESS != cResult.code) {
                //点击失败
                showConfirmDialog(cResult.error?.joinToString("\n")?:"unknown")
            } else {
                //点击成功, 延迟500毫秒刷新页面
                startRefreshScreenshot()
            }
        }
    }

    private var lastSwipeTime: Long? = null

    /**
     * startPoint和endPoint是桌面应用内的手机截屏的坐标
     */
    fun swipe(imageDisplayWidth: Int, imageDisplayHeight: Int,
              startPoint: Pair<Int, Int>, endPoint: Pair<Int, Int>) {
        viewModelScope.launch(Dispatchers.IO) {
            logger.debug("swipe: ${startPoint.first}, ${startPoint.second} -> ${endPoint.first}, ${endPoint.second}")
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path == null) {
                return@launch
            }
            val index = _curDeviceIndex.value
            val deviceList = deviceManager.getDevices()

            if (index < 0 || index >= deviceList.size) {
                return@launch
            }
            val deviceInfo = deviceList[index]
            val imageBitmap = _screenImage.value
            if (imageBitmap.width <= 0 || imageBitmap.height <= 0) {
                return@launch
            }
            val deviceStartPoint = desktopToPhone(imageDisplayWidth, imageDisplayHeight,
                imageBitmap.width, imageBitmap.height, startPoint.first, startPoint.second)
            val deviceEndPoint = desktopToPhone(imageDisplayWidth, imageDisplayHeight,
                imageBitmap.width, imageBitmap.height, endPoint.first, endPoint.second)
            val curTime = System.currentTimeMillis()
            if (lastSwipeTime != null && curTime - lastSwipeTime!! < 1000L) {
                //点击之后刷新要等500毫秒, 所以点击频率不能小于500毫秒,
                logger.debug("swipe too frequently")
                return@launch
            }
            val cResult = AndroidSdkTools.swipe(path,
                deviceSerialId = deviceInfo.serialId,
                startPoint = deviceStartPoint,
                endPoint = deviceEndPoint)
            lastSwipeTime = System.currentTimeMillis()
            if (CODE_SUCCESS != cResult.code) {
                //点击失败
                showConfirmDialog(cResult.error?.joinToString("\n")?:"unknown")
            } else {
                //点击成功, 开始自动刷新页面
                startRefreshScreenshot()
            }
        }
    }


    // 桌面应用内的点击坐标 -> 手机屏幕坐标（等比映射）
    fun desktopToPhone(imageDisplayWidth: Int, imageDisplayHeight: Int,
                       imageSrcWidth: Int, imageSrcHeight: Int,
                       pointX: Int, pointY: Int): Pair<Int, Int> {
        val scaleX = imageSrcWidth.toFloat() / imageDisplayWidth
        val scaleY = imageSrcHeight.toFloat() / imageDisplayHeight
        // 取最小缩放比例（避免拉伸，保持宽高比）
        val scale = minOf(scaleX, scaleY)
        return Pair((pointX * scale).toInt(), (pointY * scale).toInt())
    }

    /**
     * 启动任务
     */
    fun startTestTask() {
        viewModelScope.launch(Dispatchers.IO) {
            val androidSdkPath = database.getConfig(ANDROID_SDK_PATH)
            if (androidSdkPath.isNullOrEmpty()) {
                _uiDialogState.update {
                    it.copy(STATE_FAILURE, "未找到设备")
                }
                showConfirmDialog("请先安装ADB")
                return@launch
            }
            val index = _curDeviceIndex.value
            val deviceList = deviceManager.getDevices()

            if (index < 0 || index >= deviceList.size) {
                return@launch
            }
            val deviceInfo = deviceList[index]

            val work = DyjsbWork(androidSdkPath, deviceInfo.serialId)
            //暂定每个设备每次只能有一个任务
            workManager.execute(work, onProgress = { progress ->

            }, onError = { error ->
                error.printStackTrace()
            })
        }
    }

    private var refreshScreenshotJob: Job? = null

    /**
     * 开始刷新屏幕
     */
    fun startRefreshScreenshot() {
        refreshScreenshotJob?.cancel()
        refreshScreenshotJob = viewModelScope.launch(Dispatchers.IO) {
            val path = database.getConfig(ANDROID_SDK_PATH)
            if (path == null) {
                return@launch
            }
            val index = _curDeviceIndex.value
            val deviceList = deviceManager.getDevices()
            if (index < 0 || index >= deviceList.size) {
                return@launch
            }
            while(true) {
                val deviceInfo = deviceList[index]
                val bitmap = AndroidSdkTools.getScreenshot(androidSdkPath = path, deviceSerialId = deviceInfo.serialId)
                if (bitmap != null) {
                    _screenImage.update {
                        bitmap
                    }
                }
                delay(500.milliseconds)
            }
        }
    }

    override fun onCleared() {
        super.onCleared()
        refreshScreenshotJob?.cancel()
    }
}